﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using EASerialization.Serialization.MocaTree.Util;
using EASerialization.Serialization.MocaTree;

namespace EASerialization.Serialization
{
    public abstract class MocaTaggableElement : MocaSerializableElement
    {

        public static readonly String SerializationTaggedValueName = "serializedTree";

        /// <summary>
        /// The EA Object the TaggedValue should be saved to
        /// </summary>
        /// <returns></returns>
        public abstract Object getObjectToBeTagged();

        public String mocaNodeToString(MocaNode mocaNode)
        {
            //create xml stub with a single root node
            XmlDocument xmlDocStub = MocaTreeUtil.createMocaXMLDoc();
            //parse this object to moca element tree
            MocaNode treeElement = mocaNode;
            //parse moca element to xmlElement tree
            XmlElement serializedMocaRoot = treeElement.serializeToXmlTree(xmlDocStub);

            //append new xmlElement to xmlDocument
            xmlDocStub.FirstChild.AppendChild(serializedMocaRoot);
            return MocaTreeUtil.xmlDocumentToString(xmlDocStub);
        }

        /// <summary>
        /// Serializes the current Object 1. to MocaTree and 2. to XmlDocument and saves the XmlDocument 
        /// represented as String to a TaggedValue. Last some EA GUI stuff is done which is used to make sure that
        /// the visualization in EA works correctly.
        /// </summary>
        public void saveTreeToEATaggedValue(Boolean updateEaGui)
        {
            //create xml stub with a single root node
            XmlDocument xmlDocStub = MocaTreeUtil.createMocaXMLDoc();
            //parse this object to moca element tree
            MocaNode treeElement = this.serializeToMocaTree();
            //parse moca element to xmlElement tree
            XmlElement serializedMocaRoot = treeElement.serializeToXmlTree(xmlDocStub);

            //append new xmlElement to xmlDocument
            xmlDocStub.FirstChild.AppendChild(serializedMocaRoot);

            String documentString = MocaTreeUtil.xmlDocumentToString(xmlDocStub);


            EASerialization.Util.EAUtil.setTaggedValueNotes(Repository, getObjectToBeTagged(), SerializationTaggedValueName, documentString);
            if(updateEaGui)
            doEaGuiStuff();
        }

        /// <summary>
        /// Deserializes the TaggedValue from the tagged Object 
        /// </summary>
        /// <returns></returns>
        public Boolean loadTreeFromTaggedValue()
        {
            String tagNotes = "";
            Object mocaTag = EASerialization.Util.EAUtil.findTaggedValue(getObjectToBeTagged(), SerializationTaggedValueName);
            if (mocaTag is EA.TaggedValue)
                tagNotes = (mocaTag as EA.TaggedValue).Notes;
            else if (mocaTag is EA.ConnectorTag)
                tagNotes = (mocaTag as EA.ConnectorTag).Notes;
            else if (mocaTag is EA.MethodTag)
                tagNotes = (mocaTag as EA.MethodTag).Notes;

            if (tagNotes != "")
            {
                XmlDocument xmlDocument = MocaTreeUtil.stringToXmlDocument(tagNotes);
                MocaNode emptyMocaNode = new MocaNode();

                //fill mocanode from xmlElement
                emptyMocaNode.deserializeFromXmlTree(xmlDocument.FirstChild.FirstChild as XmlElement);

                
                //fill this from mocanode

                try
                {

                    deserializeFromMocaTree(emptyMocaNode);
                }
                catch
                {
                    return false;
                }
                return true;
            }
            return false;
        }


        public override MocaNode serializeToMocaTree(MocaNode actNode)
        {
            return serializeToMocaTree();
        }

        public abstract MocaNode serializeToMocaTree();


        /// <summary>
        /// necessary for the visual output in EA. 
        /// TaggedValues for shapescripts etc.
        /// </summary>
        public virtual void doEaGuiStuff()
        {
        }

    }
}
